﻿using System;
using System.Runtime.InteropServices;


namespace Lockzhiner
{

    /*
     * DAQ122采样率
     */
    enum DAQVoltage
    {
        Voltage5V = 6,
        Voltage10V = 7,
    };

    enum DAQADCChannel
    {
        None = 0b00000000,       /// 全不选 | 软件触发
        AIN1 = 0b00000001,       /// ADC通道1
        AIN2 = 0b00000001 << 1,  /// ADC通道2
        AIN3 = 0b00000001 << 2,  /// ADC通道3
        AIN4 = 0b00000001 << 3,  /// ADC通道4
        AIN5 = 0b00000001 << 4,  /// ADC通道5
        AIN6 = 0b00000001 << 5,  /// ADC通道6
        AIN7 = 0b00000001 << 6,  /// ADC通道7
        AIN8 = 0b00000001 << 7,  /// ADC通道8
        AIN_ALL = 0b11111111  ,  /// ADC通道8
    };

    enum DAQSampleRate
    {
        SampleRate100 = 100,
        SampleRate500 = 500,
        SampleRate1K = 1000,
        SampleRate5K = 5000,
        SampleRate10K = 10000,
        SampleRate50K = 50000,
        SampleRate100K = 100000,
        SampleRate200K = 200000,
    };

    /*
     * 类用途：控制DAQ122类
     */
    class DAQ122
    {
        public DAQ122()
        {
        }

        ~DAQ122()
        {
        }

        /*
         * 函数用途：创建DAQ122设备
         * 注意事项：
         *          1.  一个DAQ122类只能用于控制一个DAQ122设备
         */
        public void CreateDevice()
        {
            daq122_ = DAQ122_New();
        }

        /*
         * 函数用途：删除DAQ122设备
         * 注意事项：
         *          1.  调用了CreateDevice就必须调用DeleteDevice，否则可能出现内存泄露
         */
        public void DeleteDevice()
        {
            if (daq122_ == IntPtr.Zero) {
                return;
            }
            DAQ122_Delete(daq122_);
        }


        /*
         * 函数用途：初始化DAQ122设备
         * 注意事项：
         *          1.  必须CreateDevice后才能调用这个函数
         */
        public bool InitializeDevice()
        {
            return DAQ122_InitializeDevice(daq122_);
        }

        /*
         * 函数用途：连接DAQ122设备
         * 注意事项：
         *          1.  必须CreateDevice后才能调用这个函数
         */
        public bool ConnectedDevice()
        {
            return DAQ122_ConnectedDevice(daq122_);
        }

        public bool ConfigureADCSamplingParameters(DAQVoltage voltage, DAQSampleRate sample_rate)
        {
            UInt32 temp_voltage = (UInt32)voltage;
            UInt32 temp_sample_rate = (UInt32)sample_rate;
            return DAQ122_ConfigureSamplingParameters(daq122_, temp_voltage, temp_sample_rate);
        }

        public bool ConfigADCChannel(UInt32 channel)
        {
            return DAQ122_ConfigADCChannel(daq122_, channel);
        }

        public bool StartADCCollection()
        {
            return DAQ122_StartCollection(daq122_);
        }

        public bool StopADCCollection()
        {
            return DAQ122_StopCollection(daq122_);
        }
        
        public bool TryReadData(UInt32 channel, ref double data, UInt32 read_size, UInt32 timeout = 250)
        {
            return DAQ122_TryReadData(daq122_, channel, ref data, read_size, timeout);
        }

        public bool ADCDataBufferIsValid(UInt32 data_num) {
            return DAQ122_ADCDataBufferIsValid(daq122_, data_num);
        }


        private IntPtr daq122_;

        private const string DAQ_LIB_NAME = "libdaq-2.0.0.dll";

        // 创建DAQ122
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr DAQ122_New();

        // 删除DAQ122对象
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_Delete(IntPtr pointer);

        // 初始化DAQ122
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_InitializeDevice(IntPtr pointer);

        // 连接DAQ122
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_ConnectedDevice(IntPtr pointer);

        // 配置采样率和电压幅值
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_ConfigureSamplingParameters(IntPtr pointer, UInt32 voltage, UInt32 sampling_rate);

        // 配置ADC通道
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_ConfigADCChannel(IntPtr pointer, UInt32 channel);

        // 开始采集
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_StartCollection(IntPtr pointer);

        // 停止采集
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_StopCollection(IntPtr pointer);

        // 读取数据
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_TryReadData(IntPtr pointer, UInt32 channel, ref double data, UInt32 read_size, UInt32 timeout);

        // 判断当前所有通道缓冲区的数据量是否超过指定数值
        [DllImport(DAQ_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
        private static extern bool DAQ122_ADCDataBufferIsValid(IntPtr pointer, UInt32 data_num);
    }
}
